/**
 * 文件上传服务
 *
 * 提供文件上传相关的API接口
 */
import { api } from './api';

export interface UploadResponse {
  url: string;
  filename: string;
  size: number;
  mime_type: string;
}

// 后端API响应格式
interface BackendUploadResponse {
  filename: string;
  original_filename: string;
  file_path: string;
  file_url: string;
  file_size: number;
  content_type: string;
  width?: number;
  height?: number;
  thumbnail_url?: string;
}

export interface UploadProgress {
  loaded: number;
  total: number;
  percentage: number;
}

/**
 * 文件上传服务
 */
export const uploadService = {
  /**
   * 上传图片文件到服务器
   * @param file 要上传的文件
   * @param onProgress 上传进度回调
   * @returns 上传结果
   */
  uploadFile: async (
    file: File,
    onProgress?: (progress: UploadProgress) => void
  ): Promise<UploadResponse> => {
    const formData = new FormData();
    formData.append('file', file);

    try {
      const response = await api.post<BackendUploadResponse>('/api/upload/image', formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
        onUploadProgress: (progressEvent) => {
          if (progressEvent.total && onProgress) {
            const percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            onProgress({
              loaded: progressEvent.loaded,
              total: progressEvent.total,
              percentage
            });
          }
        }
      });

      // 转换后端响应格式到前端期望的格式
      return {
        url: response.file_url,
        filename: response.filename,
        size: response.file_size,
        mime_type: response.content_type
      };
    } catch (error: any) {
      if (error.response?.data?.detail) {
        throw new Error(error.response.data.detail);
      }
      throw new Error('上传失败，请重试');
    }
  },

  /**
   * 上传图片（带图片验证）
   * @param file 要上传的图片文件
   * @param onProgress 上传进度回调
   * @returns 上传结果
   */
  uploadImage: async (
    file: File,
    onProgress?: (progress: UploadProgress) => void
  ): Promise<UploadResponse> => {
    // 验证文件类型
    if (!file.type.startsWith('image/')) {
      throw new Error('请选择图片文件');
    }

    // 验证文件大小（限制为10MB，与后端保持一致）
    const maxSize = 10 * 1024 * 1024; // 10MB
    if (file.size > maxSize) {
      throw new Error('图片文件大小不能超过10MB');
    }

    // 验证图片格式
    const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp', 'image/gif'];
    if (!allowedTypes.includes(file.type)) {
      throw new Error('只支持 JPEG、PNG、WebP、GIF 格式的图片');
    }

    return uploadService.uploadFile(file, onProgress);
  },

  /**
   * 压缩图片
   * @param file 原始图片文件
   * @param maxWidth 最大宽度
   * @param maxHeight 最大高度
   * @param quality 压缩质量 (0-1)
   * @returns 压缩后的文件
   */
  compressImage: (
    file: File,
    maxWidth: number = 1920,
    maxHeight: number = 1080,
    quality: number = 0.8
  ): Promise<File> => {
    return new Promise((resolve, reject) => {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      const img = new Image();

      img.onload = () => {
        // 计算新的尺寸
        let { width, height } = img;
        
        if (width > maxWidth) {
          height = (height * maxWidth) / width;
          width = maxWidth;
        }
        
        if (height > maxHeight) {
          width = (width * maxHeight) / height;
          height = maxHeight;
        }

        // 设置画布尺寸
        canvas.width = width;
        canvas.height = height;

        // 绘制图片
        ctx?.drawImage(img, 0, 0, width, height);

        // 转换为Blob
        canvas.toBlob(
          (blob) => {
            if (blob) {
              const compressedFile = new File([blob], file.name, {
                type: file.type,
                lastModified: Date.now()
              });
              resolve(compressedFile);
            } else {
              reject(new Error('图片压缩失败'));
            }
          },
          file.type,
          quality
        );
      };

      img.onerror = () => {
        reject(new Error('图片加载失败'));
      };

      img.src = URL.createObjectURL(file);
    });
  },

  /**
   * 生成图片预览URL（仅用于本地预览）
   * @param file 图片文件
   * @returns 预览URL
   */
  createPreviewUrl: (file: File): string => {
    return URL.createObjectURL(file);
  },

  /**
   * 释放预览URL
   * @param url 预览URL
   */
  revokePreviewUrl: (url: string): void => {
    URL.revokeObjectURL(url);
  }
};
